package cn.echcz.spark.examples

/**
  * spark用例中可能用到的工具类
  */
object Utils {

  /**
    * 将ip地址转成Long
    *
    * @param ip ip地址
    * @return ip地址数字表示
    */
  def ip2Long(ip: String): Long = {
    val ipSplits = ip.split("\\.")
    var ipNum = 0L
    //循环ip的4个段
    for (i <- 0 until ipSplits.length){
      // 每次循环将ipNum向左移8位后，将新的段填充到低8位
      ipNum = (ipNum << 8L) | ipSplits(i).toLong
    }
    ipNum
  }

  /**
    * 通过二分查找法从一组区间中找到包含待查找值的区间索引
    * 注意: 区间集合降序排列且无重叠的
    *
    * @param num 待查找值
    * @param ranges 一组区间
    * @return 所属区间索引,如果没有找到则返回-1
    */
  def searchRange(num: Long, ranges: Array[(Long, Long)]): Int = {
    var min = 0
    var max = ranges.length - 1
    def getMid: Int = (max + min) / 2
    var mid = 0

    while (max >= min){
      mid = getMid
      if (num < ranges(mid)._1){
        max = mid - 1
      } else if (num > ranges(mid)._2){
        min = mid + 1
      } else {
        return mid
      }
    }
    -1
  }

  /**
    * 通过二分查找法从一组区间中找到包含待查找值的区间对应的标识
    *
    * @param num 待查找值
    * @param ranges 一组 区间与标识元组
    * @return 所属区间的标识符,如果没有则返回"unknown"
    */
  def searchRange2(num: Long, ranges: Array[((Long, Long), String)]): String = {
    var min = 0
    var max = ranges.length - 1
    def getMid: Int = (max + min) / 2
    var mid = 0

    while (max >= min){
      mid = getMid
      if (num < ranges(mid)._1._1){
        max = mid - 1
      } else if (num > ranges(mid)._1._2){
        min = mid + 1
      } else {
        return ranges(mid)._2
      }
    }
    "unknown"
  }



}
